/**
 * @Author: Nick Zhang <thesadboy@vip.qq.com>
 * @Description: 通用工具类
 * @Date: 2024-06-19 20:29:09
 * @LastEditors: Nick Zhang <thesadboy@vip.qq.com>
 * @LastEditTime: 2024-10-11 14:59:51
 */
package com.nickzhang.jetbrains.file_description_plugin.utils

import com.fasterxml.jackson.core.JsonParseException
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.editor.Document
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile
import com.nickzhang.jetbrains.file_description_plugin.configs.AppSettingState
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonPrimitive
import java.nio.file.Files
import java.nio.file.Paths
import java.nio.file.attribute.BasicFileAttributes
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter

class CommonUtil {
    companion object {
        /**
         * 查找文件的Project
         */
        private fun findProjectForFile(file: VirtualFile): Project? {
            val projects = ProjectManager.getInstance().openProjects
            for (project in projects) {
                if (project.basePath != null && file.path.startsWith(project.basePath!!)) {
                    return project
                }
            }
            return null
        }

        /**
         * 保存文件内容
         */
        fun saveFileContent(file: VirtualFile, document: Document, content: String) {
            val project = findProjectForFile(file) ?: return
            WriteCommandAction.runWriteCommandAction(project) {
                try {
                    document.setText(content)
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        }

        /**
         * 获取文件相对路径
         */
        fun getRelativePath(file: VirtualFile): String {
            val project = findProjectForFile(file) ?: return file.path
            val basePath = project.basePath
            return if (basePath != null) {
                val baseDir = LocalFileSystem.getInstance().findFileByPath(basePath)
                VfsUtilCore.getRelativePath(file, baseDir as VirtualFile) ?: file.path
            } else {
                file.path
            }
        }

        /**
         * JSON字符串转JsonElement
         */
        fun convertJsonStringToJson(string: String): JsonElement? {
            val str = string.replace(Regex("//[^\n\r]+", RegexOption.MULTILINE), "").trim()
            try {
                val json = Json.parseToJsonElement(str)
                if (json is JsonPrimitive) return null
                return json
            } catch (e: JsonParseException) {
                return null
            } catch (e: IllegalArgumentException) {
                return null
            }
        }

        /**
         * 获取文件创建时间
         */
        fun getFileCreationTime(virtualFile: VirtualFile): String {
            val path = Paths.get(virtualFile.path)
            val attributes = Files.readAttributes(path, BasicFileAttributes::class.java)
            val creationTime = attributes.creationTime().toInstant()
            // 将创建时间格式化为 yyyy-MM-dd HH:mm:ss 格式
            val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
            val localDateTime = LocalDateTime.ofInstant(creationTime, ZoneId.systemDefault())
            return formatter.format(localDateTime)
        }

        fun getFileExtension(file: VirtualFile): String {
            var ext = file.extension ?: ""
            if (file.name.matches(Regex("\\.env(\\.[^.]+)?"))) {
                ext = "env"
            }
            return when (ext.lowercase()) {
                "env", "yml" -> "property"
                "java", "kt", "css", "scss", "less", "ts", "tsx", "js", "jsx", "mjs", "mts", "cjs", "cts", "go", "cpp", "c", "hpp", "cu", "h", "cuh" -> "javascript"
                "html", "vue" -> "html"
                "py", "pyw", "pyi", "pxd", "pxi", "pyx" -> "python"
                "dart" -> "dart"
                "php" -> "php"
                else -> ""
            }
        }

        /**
         * 获取头部注释配置
         */
        fun getHeaderCommentConfig(): JsonElement {
            val default =
                """{"Author":"git config user.name && git config user.email","Date":"","LastEditors":"git config user.name && git config user.email","LastEditTime":"","FilePath":"","Description":"这是默认设置,可以在设置》工具》File Description中进行配置"}"""
            val config = AppSettingState.getInstance().customHeaderComment
            return convertJsonStringToJson(config) ?: Json.parseToJsonElement(default)
        }

        fun checkIsFileIsIgnored(file: VirtualFile): Boolean {
            val ignorePatterns =
                ".git/*,.idea/*,.vscode/*,node_modules/*,${AppSettingState.getInstance().ignorePaths}".split(Regex("[,\r\n]"))
                    .filter { it.isNotEmpty() }
                    .map {
                        Regex(
                            it.trim().replace(".", "\\.")
                                .replace("*", ".*")
                                .replace("?", ".")
                        )
                    }
            val filePath = getRelativePath(file)
            return ignorePatterns.any { it.matches(filePath) }
        }
    }
}
